package com.xxgc.zde.config;

import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 启用简单的消息代理，客户端可以订阅以 /topic 开头的主题
        config.enableSimpleBroker("/topic");
        // 设置应用的目的地前缀，客户端发送消息时需要以 /app 开头
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 注册一个 WebSocket 端点，客户端可以通过 /ws 连接到 WebSocket 服务，允许所有来源的跨域请求，并使用 SockJS 作为备用方案
        registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        // 为客户端入站通道添加一个拦截器
        registration.interceptors(new org.springframework.messaging.support.ChannelInterceptor() {
            @Override
            public org.springframework.messaging.Message<?> preSend(org.springframework.messaging.Message<?> message, org.springframework.messaging.MessageChannel channel) {
                // 获取消息的 Stomp 头访问器
                org.springframework.messaging.simp.stomp.StompHeaderAccessor accessor = org.springframework.messaging.simp.stomp.StompHeaderAccessor.wrap(message);
                // 检查消息的命令是否为 CONNECT，即客户端尝试连接时
                if (org.springframework.messaging.simp.stomp.StompCommand.CONNECT.equals(accessor.getCommand())) {
                    // 从请求头中获取名为 satoken 的 token
                    String token = accessor.getFirstNativeHeader("satoken");
                    if (token != null) {
                        // 设置 Sa - Token 的 token 值
                        StpUtil.setTokenValue(token);
                        // 检查用户是否已登录
                        if (StpUtil.isLogin()) {
                            // 如果已登录，允许消息继续传递
                            return message;
                        }
                    }
                    // 如果未登录或 token 无效，阻止消息传递
                    return null;
                }
                // 对于非 CONNECT 命令的消息，直接允许传递
                return message;
            }
        });
    }
}
